--[[
THIS IS THE CORE FILE OF GDATABASE!

]]
require( "mysql" )
require( "ptimer" ) --My persistant timer module
gdatabase.connections = {} --Keeps a table of all the mysql connections made

gdatabase.connectionindex = 1

--this function makes the connection to the request database and  puts the connection in the connection table, can access the database by the index returned
--takes databasehost, databaseuser, databasepassword, databasename all strings
--returns the index of the location of the database in the gdatabase.connections. Returns false is connection was unsuccessful
function gdatabase.MakeConnection(databasehost, databaseuser, databasepassword, databasename, tblSettings)
	local intIndex = gdatabase.connectionindex
	local theSettings = gdatabase.lib.loadsettings(tblSettings)
	--make the connection!
	gdatabase.connections[intIndex] = {}
	gdatabase.connections[intIndex].database, err = mysql.connect(databasehost, databaseuser, databasepassword, databasename,nil,nil,CLIENT_MULTI_RESULTS)
	
	--checks for a connection
	if (gdatabase.connections[intIndex].database == 0) then
		Msg("GDATABASE: Connection to database:" .. databasename .. "(" .. databasehost .. ") unsuccessful!!\n")
		return false
	end
	
	--connection was made! Tell the console
	Msg("GDATABASE: Connection to database:" .. databasename .. "(" .. databasehost .. ") successful!!\n")
	
	--Init all the tables and the Keep Alive that will be required.
	gdatabase.connectionindex = gdatabase.connectionindex + 1
	gdatabase.connections[intIndex].databasename = databasename
	gdatabase.connections[intIndex].settings = theSettings
	gdatabase.connections[intIndex].hooks = {}
	gdatabase.connections[intIndex].status = true
	gdatabase.connections[intIndex].threads = {}
	gdatabase.connections[intIndex].threads.queue = {}
	gdatabase.connections[intIndex].threads.active = {}
	gdatabase.connections[intIndex].threads.queuetime = 0
	gdatabase.connections[intIndex].threads.processing = 0
	gdatabase.connections[intIndex].databasehost = databasehost
	gdatabase.connections[intIndex].databaseuser = databaseuser
	gdatabase.connections[intIndex].databasepassword = databasepassword
	gdatabase.lib.keepalive(intIndex)

	return intIndex

end

--Removes the connection from the table and stops keep alive function related to it
--Takes databaseindex 
--Returns if the connection was successful
function gdatabase.KillConnection(intDatabaseIndex)
	--1st check to see if the connection is active	
	if(!gdatabase.CheckForConnection(intDatabaseIndex)) then
		Msg("GDATABASE: Database DOESNT exist!! Therefore cannot be killed!\n")	
		return false
	end	
	local connection = gdatabase.connections[intDatabaseIndex]
	gdatabase.lib.killconnection(intDatabaseIndex)
	--tell the console the connection was killed
	Msg("GDATABASE: Connection to database:" .. connection.databasename .. "(" .. connection.databasehost .. ") killed!!!\n")
	--nil the database connection in the table
	gdatabase.connections[intDatabaseIndex] = nil
	
	--kill the keep alive timer
	ptimer.Remove("gdatabase_keepalive_index_" .. intDatabaseIndex)
	ptimer.RemoveGroup("gdatabase_connection" .. intDatabaseIndex)
	
	return true
end

--Queries the database 
--takes strQuery(string query), intDatabase(database index)
--returns the table on query result
function gdatabase.Query(strQuery, intDatabaseIndex)
	intDatabaseIndex = intDatabaseIndex or 0
	if(!gdatabase.CheckForConnection(intDatabaseIndex) or intDatabaseIndex == nil) then
		Msg("GDATABASE: Query Failure:" .. intDatabaseIndex .. " INDEX DOESN'T EXIST\n")
		return false
	end

	if gdatabase.config.debug then
		Msg("DEBUG: Querying on connection #" .. intDatabaseIndex .. "\n")
	end
	
	local tq, k, err = mysql.query(gdatabase.connections[intDatabaseIndex].database, strQuery)
	
	if(!k) then
		Msg("GDATABASE: Query Error:" .. err .. "\n")
		return false
	end
	
	--Run the hook table
	gdatabase.lib.runhooks("query", intDatabaseIndex)

	return tq
end

--returns if the database exists or not.
--takes intDatabaseIndex
--returns if the database connection exists
function gdatabase.CheckForConnection(intDatabaseIndex)
	if(gdatabase.connections[intDatabaseIndex] ~= nil) then
		if(gdatabase.connections[intDatabaseIndex].database == 0 or gdatabase.connections[intDatabaseIndex].database == nil) then
			return false
		
		else
			return true
		end
	else
		return false
	end
end

function gdatabase.CleanString(intDatabaseIndex, strString)
	return mysql.escape(gdatabase.connections[intDatabaseIndex].database, strString)
end

--adds to the hook table
function gdatabase.HookAdd(strHook, strUniqueName, fnHookFunction, intDatabaseIndex, ...)
	if(strHook == nil or strUniqueName == nil or type(fnHookFunction) ~= "function" or intDatabaseIndex == nil) then return false end

--check that the database exists and is connected
	if(!gdatabase.CheckForConnection(intDatabaseIndex)) then
		Msg("GDATABASE: Hook ADD Failure: INDEX DOESN'T EXIST OR TIMEDOUT!\n")
		return false
	end
	
	local tblHooks = gdatabase.connections[intDatabaseIndex].hooks
	
--adds the hook table if it doesnt exist
	if tblHooks[strHook] == nil then
		tblHooks[strHook] = {}
	end
	tblHooks[strHook][strUniqueName] = {}
	tblHooks[strHook][strUniqueName].Func = fnHookFunction
	
	if arg != nil then
		tblHooks[strHook][strUniqueName].Args = arg
	end
end

--Removes from the hook table
function gdatabase.HookRemove(strHook, strUniqueName, intDatabaseIndex)
	if(strHook == nil or strUniqueName == nil or intDatabaseIndex == nil) then return false end

--check that the database exists and is connected
	if(!gdatabase.CheckForConnection(intDatabaseIndex)) then
			Msg("GDATABASE: Hook Remove Failure: INDEX DOESN'T EXIST OR TIMEDOUT!\n")
			return false
	end

--Returns false if hook table doesnt exist
	if gdatabase.connections[intDatabaseIndex].hooks[strHook] == nil then
		return false
	end

	gdatabase.connections[intDatabaseIndex].hooks[strHook][strUniqueName] = nil
end

--These functions are wrappers for ptimer's group function. By using this these timers will be attached to the database and will be stopped automatically if the connection goes down.
function gdatabase.AddTimer(strID, intInterval, intRep, intDatabaseIndex, fnCallback, ...)
	ptimer.Add2(strID, "gdatabase_connection" .. intDatabaseIndex, intInterval, intRep, fnCallback, unpack(arg))
end

function gdatabase.RemoveTimer(strID, intDatabaseIndex)
	ptimer.Remove(strID, "gdatabase_connection" .. intDatabaseIndex)
end
